package com.aididi.designpatter;

/**
 * @Auther: xuzexiang
 * @Date: 2018-10-26 0026 21:50
 * @Description:    使用场景： 1、要求生产唯一序列号。
 *                      2、WEB 中的计数器，不用每次刷新都在数据库里加一次，用单例先缓存起来。
 *                      3、创建的一个对象需要消耗的资源过多，比如 I/O 与数据库的连接等。
*           注意事项：getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
 */
public class SingletonDemo {
    public static void main(String[] args) {
        Singleton s1 = null; // 声明对象
        Singleton s2 = null; // 声明对象
        Singleton s3 = null; // 声明对象
        s1 = Singleton.getInstance(); // 取得实例化对象
        s2 = Singleton.getInstance(); // 取得实例化对象
        s3 = Singleton.getInstance(); // 取得实例化对象
        s1.print(); // 调用方法
        s2.print(); // 调用方法
        s3.print(); // 调用方法
    }
}
/**
 *  单例模式的实现：饿汉式,线程安全 但效率比较低
 */
class Singleton{
    //在内部产生本类的实例化对象
    private static Singleton singleton = new Singleton();
    /**
     * 通过静态方法返回instance对象
     */
    public static Singleton getInstance(){
        return singleton;
    }
    /**
     * 将构造方法封装为私有化
     */
    private Singleton(){

    }
    public void print() {
        System.out.println("Hello World!!!");
    }
}

/**
 * 单例模式的实现：懒汉式,非线程安全
 */
class Singleton2{
    private Singleton2(){

    }
    private static Singleton2 singleton2;
    public static Singleton2 getInstance(){
        if(singleton2 == null)
            singleton2 = new Singleton2();
        return singleton2;
    }
}
/**
 * 懒汉式，线程安全
 */
class Singleton3 {
    private static Singleton3 instance;
    private Singleton3 (){}
    public static synchronized Singleton3 getInstance() {
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;
    }
}

/**
 * 双检锁/双重校验锁 ,线程安全
 */
class Singleton4{
    private static volatile Singleton4 singleton4;
    private Singleton4(){

    }
    private static Singleton4 getInstance(){
        if(singleton4 ==null){
            synchronized (Singleton4.class){
                if(singleton4 == null){
                    singleton4 = new Singleton4();
                }
            }
        }
        return singleton4;
    }
}

/**
 *  登记式/静态内部类 ,线程安全
 */
class Singleton5 {
    private static class SingletonHolder {
        private static final Singleton5 INSTANCE = new Singleton5();
    }
    private Singleton5 (){}
    public static final Singleton5 getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

/**
 *  枚举 ,线程安全
 */
enum Singleton6 {
    INSTANCE;
    public void whateverMethod() {
    }
}
